﻿package client_gui_chat;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.io.File;
import java.net.URL;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

import utils.Constants;
import utils.ImageCreator;
import client.ClientSocketConnection;
import client.ClientUser;
import client_gui.ClientWindow;
import client_gui.RegisterDialog;
import client_tree.User;

/**
 * Klasa predstavlja Chat Dijalog.
 * 
 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
 */
public class ChatDialog extends JFrame implements Constants { 

	private static final long serialVersionUID = 1L;

	/**
	 * Vlasnik chat dijaloga.
	 */
	private ClientWindow owner = null;
	
	/**
	 * Client korisnike aplikacije.
	 */
	private ClientUser clientUser = null;
	
	/**
	 * Korisnik sa kojim se chatuje.
	 */
	private User user = null;
	
	/*
	 * Stanja koja se koriste kod procesiranja ulaza sa tastature.
	 */
	private final int INIT_STATE = 0;
	private final int ICON_STATE = 1;
	
	private int state = INIT_STATE;
	
	
	/**
	 * Konekcija kojom se odvija chat.
	 */
	private ClientSocketConnection connection = null;

	/**
	 * Hash tabela sa ikonicama smajlija.
	 */
	private Hashtable<String, ImageIcon> emoticonsTable = new Hashtable<String, ImageIcon>();
	
	/**
	 * Dokument clientUserTextPane-a.
	 */
	private StyledDocument clientUserTextPaneDocument = null;
	
	/**
	 * Dokument userTextPane-a.
	 */
	private StyledDocument userTextPaneDocument = null;
	
	
	// GUI atributi
	
	private Toolkit kit;
	
	private JPanel jContentPane = null;

	private JMenuBar jJMenuBar = null;
	
	private JMenu fileMenu = null;
	private JMenu editMenu = null;
	private JMenu helpMenu = null;

	private JSplitPane splitPane = null;
	private JScrollPane userScrollPane = null;
	private JTextPane userTextPane = null;
	private JPanel clientUserPanel = null;
	private JToolBar toolBar = null;
	private JScrollPane clientUserScrollPane = null;
	private JTextPane clientUserTextPane = null;
	
	
	private JButton smilesButton;
	private JPopupMenu smilesContextMenu;
	
	private Color backgroundColor = Color.WHITE;
	private JButton sendButton = null;
	private JButton fontButton = null;
	private JButton backgroundButton = null;
	
	private JPanel statusLine = null;
	private JLabel typingText = null;
	
	private static final Font typingTextFont = new Font("Arial", Font.BOLD, 11);

	private TypingThread typingThread = null;
	private Timer timer = null;
	private TimerTypingTask timerTask = null;
	private static final int TIMER_DELAY = 3000;

	

	
	/**
	 * Konstruktor.
	 * @param owner - glavni prozor aplikacje
	 * @param user - korisnik sa kojim se chatuje
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public ChatDialog(ClientWindow owner, User user) {
		super("CHAT: " + owner.getApplicaton().getClientUser().getNickname() + " --> " + user.getNickname());
		
		this.user = user;
		
		this.owner = owner;
		
		this.clientUser = owner.getApplicaton().getClientUser();
		
		// popunjavanje hash tabele sa ikonicama
		loadEmoticonsTable();

		initialize();
		
		this.addWindowListener(new ChatWindowHandler(this));
		
		typingThread = new TypingThread(owner.getApplicaton(), this);		
		timerTask = new TimerTypingTask();
		timer = new Timer(TIMER_DELAY, timerTask);
		
		startTypingListener();
	}

	

	
	/**
	 * Task koji reprezentuje task koji se periodicno izvrasva (svakih TIMER_DELAY ms).
	 * Nakon isteka ovog vremena setuje se da je user neaktivan.
	 * Inace, ukoliko user otkuca karakter, timer se resetuje.
	 * Nakon svakog isteka vremena koje ceka timer, izvrsi se ovaj task.
	 * 
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private class TimerTypingTask implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			typingThread.setTyping(false);
		}
	}
	
	/**
	 * Metod stopira typing listener.
	 */
	public void stopTypingListener() {
		timer.stop();
		typingThread.setRunning(false);
		hideTyping();
	}
	
	
	/**
	 * Metod startuje typing listener.
	 */
	public void startTypingListener() {
		typingThread = new TypingThread(owner.getApplicaton(), this);
		typingThread.setRunning(true);
		typingThread.start();
		timer.start();
	}
	
	
	private void initialize() {
		this.setSize(720, 400);
		this.setJMenuBar(getJJMenuBar());
		this.setLocation(owner.getX() + owner.getWidth() / 2 - this.getWidth() / 2, owner.getY() + owner.getHeight() / 2 - this.getHeight() / 2);
		this.setResizable(true);
		this.setContentPane(getChatStreamSplitPane());
		
		kit = this.getToolkit();
		URL url = ClientWindow.class.getResource("/client_gui_chat/chat_icon.png");
		this.setIconImage(kit.createImage(url));
		
		this.addWindowStateListener(new WindowStateListener() {
			public void windowStateChanged(WindowEvent e) {
				int h = getHeight();

				splitPane.setDividerLocation(h/2);
				
				SwingUtilities.updateComponentTreeUI(ChatDialog.this);
			}
		});
		
		loadStyles();
	}

	private JSplitPane chatStreamSplitPane = null;
	
	private JSplitPane getChatStreamSplitPane() {
		if (chatStreamSplitPane == null) {
			chatStreamSplitPane = new JSplitPane();
			
			chatStreamSplitPane.setOpaque(true);
			
			chatStreamSplitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
			chatStreamSplitPane.setLeftComponent(getChatPanel());
			chatStreamSplitPane.setRightComponent(getStreamingPanel());
			
//			chatStreamSplitPane.setMinimumSize(new Dimension(200, 0));

//			int w = this.getWidth();
//			chatStreamSplitPane.setDividerLocation(w/2);
		}
		return chatStreamSplitPane;
	}
	
	private StreamingPanel streamingPanel = null;
	
	public StreamingPanel getStreamingPanel() {
		if (streamingPanel == null) {
			streamingPanel = new StreamingPanel(this);
		}
		return streamingPanel;
	}
	
	
	private JPanel getChatPanel() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getSplitPane(), BorderLayout.CENTER);
		}
		return jContentPane;
	}


	private JMenuBar getJJMenuBar() {
		if (jJMenuBar == null) {
			jJMenuBar = new JMenuBar();
			
			jJMenuBar.add(getFileMenu());
			jJMenuBar.add(getEditMenu());
			jJMenuBar.add(getHelpMenu());
		}
		return jJMenuBar;
	}

	
	
	private JSplitPane getSplitPane() {
		if (splitPane == null) {
			splitPane = new JSplitPane();
			
			splitPane.setOpaque(true);
			
			splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
			splitPane.setBottomComponent(getClientUserPanel());
			splitPane.setTopComponent(getUserScrollPane());

			splitPane.getTopComponent().setMinimumSize(new Dimension(50,80));
			splitPane.getBottomComponent().setMinimumSize(new Dimension(50,100));
			
			int h = this.getHeight();

			splitPane.setDividerLocation(h/2);
		}
		return splitPane;
	}


	private JScrollPane getUserScrollPane() {
		if (userScrollPane == null) {
			userScrollPane = new JScrollPane();
			userScrollPane.setViewportView(getUserTextPane());
		}
		return userScrollPane;
	}


	private JTextPane getUserTextPane() {
		if (userTextPane == null) {
			userTextPane = new JTextPane();
			userTextPane.setEditable(false);
			userTextPane.setBackground(clientUser.getBackgroundColor());
			userTextPane.setFont(new Font(clientUser.getFontName(), clientUser.getFontStyle(), clientUser.getFontSize()));
			userTextPane.setForeground(clientUser.getFontColor());
			
			userTextPaneDocument = userTextPane.getStyledDocument();
		}
		return userTextPane;
	}


	private JPanel getClientUserPanel() {
		if (clientUserPanel == null) {
			clientUserPanel = new JPanel();
			clientUserPanel.setLayout(new BorderLayout());
			clientUserPanel.add(getToolBar(), BorderLayout.NORTH);
			clientUserPanel.add(getClientUserScrollPane(), BorderLayout.CENTER);
			clientUserPanel.add(getStatusLine(), BorderLayout.SOUTH);
		}
		return clientUserPanel;
	}


	
	private JLabel getTypingText() {
		if (typingText == null) {
			typingText = new JLabel();
			typingText.setFont(typingTextFont);
		}
		return typingText;
	}
	
	public void showTyping() {
		typingText.setText(getUser().getNickname() + " is typing...");
	}
	
	public void hideTyping() {
		typingText.setText("");
	}

	private JPanel getStatusLine() {
		if (statusLine == null) {
			statusLine = new JPanel();
			statusLine.setPreferredSize(new Dimension(100,20));
			
//			FlowLayout fl = new FlowLayout(FlowLayout.LEFT);
//			statusLine.setLayout(fl);
			
			GridBagLayout gb = new GridBagLayout();
			GridBagConstraints c = new GridBagConstraints();
			statusLine.setLayout(gb);
			
			c.gridx = 0;
			c.gridy = 0;
			c.weightx = 1;
			c.weighty = 1;
			c.anchor = GridBagConstraints.WEST;
			c.insets = new Insets(0,2,0,0);
			
			getTypingText();
			hideTyping();
			
			gb.addLayoutComponent(typingText, c);
			
//			c.gridx = 1;
//			c.gridy = 0;
//			c.weightx = 1;
//			c.weighty = 1;
//			c.anchor = GridBagConstraints.EAST;
//			c.insets = new Insets(2,0,0,2);
//			
//			gb.addLayoutComponent(getProgressBar(), c);
//
			statusLine.add(typingText);
//			statusLine.add(getProgressBar());
		}
		return statusLine;
	}
	
	
	private JToolBar getToolBar() {
		if (toolBar == null) {
			toolBar = new JToolBar();
			toolBar.setFloatable(false);
			
			toolBar.add(new SmileButton(":)"));
			toolBar.add(new SmileButton(":("));
			toolBar.add(new SmileButton(":d"));
			toolBar.add(new SmileButton(":^"));
			toolBar.add(new SmileButton(":o"));
			toolBar.add(new SmileButton(":s"));
			toolBar.add(new SmileButton(":#"));
			toolBar.add(new SmileButton(":p"));
			toolBar.add(new SmileButton(":$"));
			toolBar.add(new SmileButton(":@"));
			
			// druga dugmad
			
			toolBar.add(getSmilesButton());
			
			toolBar.addSeparator();
			
			toolBar.add(getFontButton());
			
			toolBar.add(getBackgroundButton());
			
			toolBar.addSeparator();

			toolBar.add(getSendButton());
			
//			toolBar.addSeparator();
//			
//			toolBar.add(getAudioStreamingButton());
//			toolBar.add(getVideoStreamingButton());
//			
//			toolBar.addSeparator();
//
//			toolBar.add(getStopCallButton());
		}
		return toolBar;
	}


	private JButton getSendButton() {
		if (sendButton == null) {
			sendButton = new JButton("Send <Enter>");
			sendButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					
					if (connection == null) {
						owner.getActionManager().getSendMessageAction().setUserExternal(user);
						
						owner.getActionManager().getSendMessageAction().actionPerformed(e);
					}
					
					String xxxMessage = clientUserTextPane.getText();
					
					writeUserSaysMessage(clientUser.getNickname() + " says:\n");
					writeMessage(xxxMessage);
					
					String message = clientUserTextPane.getText().trim().replace("\r\n", "¥");
					
//					message = message.replace("\t", "♦");
					
					// TODO koriscen NO_BUFFERING
//					connection.setMessage(NO_BUFFERING, "CLIENT_SEND_MSG " + owner.getApplicaton().getClientUser().getUsername() + " " + message);

					connection.writeData("CLIENT_SEND_MSG " + owner.getApplicaton().getClientUser().getUsername() + " " + message);
					
					clientUserTextPane.setText("");
				}
			});
		}
		
		return sendButton;
	}
	
	

	
	private JButton getFontButton() {
		if (fontButton == null) {
			fontButton = new JButton();
			fontButton.setIcon(ImageCreator.createImageIcon(ChatDialog.class, "/client_gui_chat/font.png"));
			
			fontButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					FontDialog fd = new FontDialog(ChatDialog.this);
					fd.setVisible(true);
				}
			});
		}
		
		return fontButton;
	}
	
	
	private JButton getBackgroundButton() {
		if (backgroundButton == null) {
			backgroundButton = new JButton();
			backgroundButton.setIcon(ImageCreator.createImageIcon(ChatDialog.class, "/client_gui_chat/color.png"));
			backgroundButton.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					backgroundColor = JColorChooser.showDialog(ChatDialog.this, "Select Custom Color", backgroundColor);
					
					if (backgroundColor == null) {
						return;
					}

					clientUser.setBackgroundColor(backgroundColor);
					userTextPane.setBackground(backgroundColor);
					clientUserTextPane.setBackground(backgroundColor);
				}
			});
		}
		
		return backgroundButton;
	}
	
	
	private JScrollPane getClientUserScrollPane() {
		if (clientUserScrollPane == null) {
			clientUserScrollPane = new JScrollPane();
			clientUserScrollPane.setViewportView(getClientUserTextPane());
		}
		return clientUserScrollPane;
	}

	


	private JTextPane getClientUserTextPane() {
		if (clientUserTextPane == null) {
			clientUserTextPane = new JTextPane();
			clientUserTextPane.setBackground(clientUser.getBackgroundColor());
			clientUserTextPane.setFont(new Font(clientUser.getFontName(), clientUser.getFontStyle(), clientUser.getFontSize()));
			clientUserTextPane.setForeground(clientUser.getFontColor());
			
			clientUserTextPaneDocument = clientUserTextPane.getStyledDocument();;
			
			/*
			 * InputMap i ActionMap za JTextPane 
			 */
			InputMap inputMap =  clientUserTextPane.getInputMap();
			ActionMap actionMap = clientUserTextPane.getActionMap();
			
			/*
			 * StyledDocument za komponentu
			 */			
			
			/*
			 * 
			 */
			KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
			KeyStroke enterCTRLkey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, KeyEvent.CTRL_MASK);
			KeyStroke pasteKey = KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK);
			KeyStroke tabKey = KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0);
			
			inputMap.put(enterKey, "enter");
			inputMap.put(pasteKey, "paste");
			inputMap.put(tabKey, "tab");

			/*
			 * Definisana default akcija za kombinaciju tastera CTRL+ENTER. Omogucava
			 * prelazak u novi red.
			 */
			inputMap.put(enterCTRLkey, DefaultEditorKit.insertBreakAction);
			
			
			/*
			 * Akcija koja se aktivira pritiskom na enter. Poziva dugme za slanje poruke
			 * udaljenom klijentu.
			 */
			actionMap.put("enter", new AbstractAction() {
				public void actionPerformed(ActionEvent e) {
					getSendButton().doClick();
				}
			});

			
			/*
			 * Ignorisanje TAB tastera.
			 */
			actionMap.put("tab", new AbstractAction() {
				public void actionPerformed(ActionEvent arg0) {				
					// do nothing
				}
			});

			
			
			/*
			 * Ignorisanje PASTE akcije.
			 */
			actionMap.put("paste", new AbstractAction() {
				public void actionPerformed(ActionEvent e) {
/*
					Action pasteAction = TransferHandler.getPasteAction();
					pasteAction.actionPerformed(e);
					
					String t = clientUserTextPane.getText();
					
					try {
						clientUserTextPaneDocument.remove(0, clientUserTextPaneDocument.getLength());
						
					} catch (BadLocationException e1) {
						e1.printStackTrace();
					}
					
					convertSmilesToIcons(t);
*/
				}
			});
			
			
			clientUserTextPane.addKeyListener(new KeyListener() {
				
				public void keyReleased(KeyEvent e) {
					if (state == ICON_STATE) {
						int b = clientUserTextPane.getCaretPosition();
						int a = b - 1;
						clientUserTextPane.select(a, b);
						clientUserTextPane.replaceSelection("");
						state = INIT_STATE;
					}
					
					// TODO typing detection
					typingThread.setTyping(true);
					timer.restart();
				}
				
				public void keyPressed(KeyEvent e) {
					
					String regExp = "^[)oO^sS#dDpP($@bBlLkKfFuUaAwWgGyYnNcCrR]$";
					Pattern pattern = Pattern.compile(regExp);
					

					char c = e.getKeyChar();
					Matcher matcher = pattern.matcher(Character.toString(c));
					int endPos = clientUserTextPaneDocument.getLength(); 
					
					if( matcher.matches() ) {
						try {
							if (  endPos > 0  && clientUserTextPaneDocument.getText(
									clientUserTextPane.getCaretPosition()-1, 1).equals(":")) {
								
								smileyConverter(c, true);
								return;
							}					
							
						} catch (BadLocationException e1) {
//							e1.printStackTrace();
						}
					}
					
					if (c == ':' ) {
						if(clientUserTextPane.getCaretPosition() < clientUserTextPane.getText().length()) {
							char afterColon = clientUserTextPane.getText().charAt(clientUserTextPane.getCaretPosition());
							smileyConverter(afterColon, false);
						}
					}
					
			
				}
				
				public void keyTyped(KeyEvent e) { }
			});

		}
		return clientUserTextPane;
	}
	
	
	

	private JMenu getFileMenu() {
		if (fileMenu == null) {
			fileMenu = new JMenu();
			fileMenu.setText("File");
			fileMenu.setMnemonic('f');
			
			fileMenu.add("Close");
		}
		return fileMenu;
	}
	
	private JMenu getEditMenu() {
		if (editMenu == null) {
			editMenu = new JMenu();
			editMenu.setText("Edit");
			editMenu.setMnemonic('e');
			
			editMenu.add("Cut");
			editMenu.add("Copy");
			editMenu.add("Paste");
		}
		return editMenu;
	}
	

	private JMenu getHelpMenu() {
		if (helpMenu == null) {
			helpMenu = new JMenu();
			helpMenu.setText("Help");
			helpMenu.setMnemonic('h');
			
			helpMenu.add("Help");
			helpMenu.add("About");
		}
		return helpMenu;
	}
	
	
	private JButton getSmilesButton() {
		if (smilesButton == null) {
			smilesButton = new JButton();
			smilesButton.setIcon(ImageCreator.createImageIcon(ChatDialog.class, "/client_gui_chat/smiles.png"));
			
			smilesButton.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseReleased(MouseEvent e) {
					
					int x = 0;
					int y = smilesButton.getHeight();
					
					ChatDialog.this.getSmilesContextMenu().show((Component)e.getSource(), x, y);
				}
			});
		}
		
		return smilesButton;
	}
	
	
	private JPopupMenu getSmilesContextMenu() {
		if (smilesContextMenu == null) {
			smilesContextMenu = new JPopupMenu();
			
			smilesContextMenu.setPreferredSize(new Dimension(160,130));
			
			FlowLayout flow = new FlowLayout(FlowLayout.CENTER);
			flow.setHgap(10);
			flow.setVgap(10);
			
			smilesContextMenu.setLayout(flow);
			
			smilesContextMenu.add(new SmileButton(":b"));
			smilesContextMenu.add(new SmileButton(":l"));
			smilesContextMenu.add(new SmileButton(":k"));
			smilesContextMenu.add(new SmileButton(":f"));
			smilesContextMenu.add(new SmileButton(":u"));
			smilesContextMenu.add(new SmileButton(":a"));
			smilesContextMenu.add(new SmileButton(":w"));
			smilesContextMenu.add(new SmileButton(":g"));
			smilesContextMenu.add(new SmileButton(":y"));
			smilesContextMenu.add(new SmileButton(":n"));
			smilesContextMenu.add(new SmileButton(":c"));
			smilesContextMenu.add(new SmileButton(":r"));
		}
		
		return smilesContextMenu;
	}
	
	
	
	/**
	 * Metod setuje client-ov avatar.
	 * @param avatarID - avatar koji se setuje
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void setAvatar(String avatarID) {
		streamingPanel.getUserAvatarButton().setIcon(ImageCreator.createImageIcon(RegisterDialog.class, "/avatars/" + avatarID + ".png"));
	}

	
	/**
	 * Metod vraca referencu na vlasnika chat dijaloga.
	 * @return - vlasnik dijaloga\
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public ClientWindow getChatOwner() {
		return this.owner;
	}

	
	/**
	 * Metod radi enable/disable Send dugmeta, u zavisnosti od prosledjenog flag-a.
	 * @param flag - enable/disable indikator
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void setSendButtonRights(boolean flag) {
		this.sendButton.setEnabled(flag);
	}
	

	/**
	 * Metod setuje konekciju za koju je vezan chat dijalog.
	 * @param connection - konekcija izmadju chat klijenata
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void setConnection(ClientSocketConnection connection) {
		this.connection = connection;
	}
	
	public ClientSocketConnection getConnection() {
		return connection;
	}
	
	
	/**
	 * Metod vraca referencu na korisnika chat dijaloga.
	 * @return - client korisnik dijaloga
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public ClientUser getClientUser() {
		return this.clientUser;
	}

	
	/**
	 * Metod vraca referencu na korisnika sa kojim se chatuje.
	 * @return - korisnik sa kojim se chatuje
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public User getUser() {
		return this.user;
	}
	
	
	/**
	 * Metod osvezava avatar, pri promeni avatara korisnika sa kojim se chatuje.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void refreshUserAvatar() {
		streamingPanel.getPeerAvatarButton().setIcon(ImageCreator.createImageIcon(ChatDialog.class, "/avatars/" + user.getAvatar() + ".png"));
	}
	
	
	/**
	 * Metod osvezava title chat dijaloga, pri promeni Nickname-a korisnika sa kojim se chatuje.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void refreshTitle() {
		this.setTitle("CHAT: " + clientUser.getNickname() + " --> " + user.getNickname());
	}
	
	
	/**
	 * Metod postavlja font na panele chat dijaloga.
	 * @param font - font koji treba setovati
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void setPanelsFont(Font font) {
		userTextPane.setFont(font);
		clientUserTextPane.setFont(font);
		clientUserTextPane.setForeground(clientUser.getFontColor());
		userTextPane.setForeground(clientUser.getFontColor());
	}
	
	
	/**
	 * Metod cisti panel korisnika (klijenta) aplikacije.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void clearDialog() {
		clientUserTextPane.setText("");
	}
	

	/**
	 * Metod ispisuje poruku na panel korisnika sa kojim se chatuje.
	 * @param message - poruka koja stize od korisnika sa kojim se chatuje.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void writeMessage(String message) {
		message = message.replace("¥", "\r\n");
//		message = message.replace("♦", "\t");
		
		convertSmilesToIcons(message + "\n");
		
		userTextPane.setCaretPosition(userTextPane.getDocument().getLength());
	}

	
	/**
	 * Metod ispisuje poruku "Nickname says: " u panel korisnika sa kojim se chatuje.
	 * @param message - poruka koja se ispisuje.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	public void writeUserSaysMessage(String message) {
		
		Style userSaysStyle = userTextPaneDocument.getStyle("bold");
		
		int length = userTextPaneDocument.getLength();

		try {
			userTextPaneDocument.insertString(length, message, userSaysStyle);
		}
		catch (BadLocationException e) {
			e.printStackTrace();
		}
	}

	

	/**
	 * Klasa predstavlja dugme smile-a.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	private class SmileButton extends JButton implements ActionListener {
		
		private String smileCode = null;
		
		public SmileButton(String smileCode) {
			this.smileCode = smileCode;

			this.setIcon(emoticonsTable.get(smileCode));
			
			this.setToolTipText(smileCode);
			
			this.addActionListener(this);
			
			this.setPreferredSize(new Dimension(28,28));
		}
		
		public void actionPerformed(ActionEvent e) {
			int b = clientUserTextPane.getCaretPosition();
			Style style = clientUserTextPaneDocument.getStyle(this.smileCode);
			
			try {
				clientUserTextPaneDocument.insertString(b, this.smileCode, style);
			}
			catch (BadLocationException e1) {
				e1.printStackTrace();
			}
			
			ChatDialog.this.getSmilesContextMenu().setVisible(false);
		}
	}
	
	
	/**
	 * Metod ucitava stilove u dokumente panela.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	private void loadStyles() {
		File iconsFiles = new File("./emoticons/");
		
		String[] iconsNames = iconsFiles.list();
		
		for (int i = 0; i < iconsNames.length; i++) {
			String name = iconsNames[i];
			int ind = name.lastIndexOf(".");
			
			String noColonName = name.substring(0, ind);
			
			String colonName = ":";
			colonName = colonName.concat(noColonName);
			
			Style tempStyle = clientUserTextPaneDocument.addStyle(colonName, null);
			StyleConstants.setAlignment(tempStyle, StyleConstants.ALIGN_CENTER);
			StyleConstants.setIcon(tempStyle, emoticonsTable.get(colonName));
			
			tempStyle = userTextPaneDocument.addStyle(colonName, null);
			StyleConstants.setAlignment(tempStyle, StyleConstants.ALIGN_CENTER);
			StyleConstants.setIcon(tempStyle, emoticonsTable.get(colonName));
		}
		
		Style userSaysStyle = userTextPaneDocument.addStyle("bold", null);
		StyleConstants.setBold(userSaysStyle, true);
		StyleConstants.setItalic(userSaysStyle,	true);
	}
	
	
	/**
	 * Metod popunjava hash tabelu ikonicama.
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	private void loadEmoticonsTable() {
		
		File iconsFiles = new File("./emoticons/");
		
		String[] iconsNames = iconsFiles.list();
		
		for (int i = 0; i < iconsNames.length; i++) {
			String name = iconsNames[i];
			int ind = name.lastIndexOf(".");
			
			String noColonName = name.substring(0, ind);
			
			String colonName = ":";
			colonName = colonName.concat(noColonName);
			
			emoticonsTable.put(colonName, ImageCreator.createImageIcon(ChatDialog.class, "/emoticons/" + name));
		}
	}
	
	
	/**
	 * Procesira ulaz sa tastature.
	 * @param smiley - karakter koji u kombinaciji sa : predstavlja stil (smiley)
	 * @param flag - indikuje polozaj : u odnosu na karakter sa kojim : kreiraju smiley
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
	private void smileyConverter(char smiley, boolean flag) {
		boolean post = flag;
		
		int a, b = clientUserTextPane.getCaretPosition();
		/*
		 * Potrebno zbog moguceg umetanja zagrade ispred odnosno iza karaktera sa kojim, u kombinaciji,
		 * komponenta renderuje smajli.
		 */
		if (post)
			a = b-1;
		else {
			a = b;
			b++;
		}						
	
		String smileyCode = ":" + Character.toString(smiley).toLowerCase();
		state = ICON_STATE;
		
		
		clientUserTextPane.select(a, b);
		clientUserTextPane.replaceSelection(" ");
		Style style = clientUserTextPaneDocument.getStyle(smileyCode);
		
		if (style == null)
			return;
		
		try {
			clientUserTextPaneDocument.insertString(b, smileyCode, style);
		}
		catch (BadLocationException er) {
			er.printStackTrace();
		}
	}
	
	
	
	/**
	 * Metod konvertuje ulazni string u smajlije, ukoliko se prepozna kod smajlija.
	 * @param inputText - ulazni tekst
	 * @author UrosKrkic & Radivoje Popovic & Martin Jondzic
	 */
    private void convertSmilesToIcons(String inputText) {
		try {
		
			int length = userTextPaneDocument.getLength();
			
			char[] chars = inputText.toCharArray();
			
			for (int i = 0; i < chars.length; i++) {
				if (chars[i] == ':') {
					
					switch (chars[i+1]) {
						case ')':
						{
							Style s = userTextPaneDocument.getStyle(":)");
							userTextPaneDocument.insertString(length+i, ":)", s);
							i++;
							continue;
						}
						case 'o':
						case 'O':
						{
							Style s = userTextPaneDocument.getStyle(":o");
							userTextPaneDocument.insertString(length+i, ":o", s);
							i++;
							continue;
						}
						case '^':
						{
							Style s = userTextPaneDocument.getStyle(":^");
							userTextPaneDocument.insertString(length+i, ":^", s);
							i++;
							continue;
						}
						case 's':
						case 'S':
						{
							Style s = userTextPaneDocument.getStyle(":)");
							userTextPaneDocument.insertString(length+i, ":)", s);
							i++;
							continue;
						}
						case '#':
						{
							Style s = userTextPaneDocument.getStyle(":#");
							userTextPaneDocument.insertString(length+i, ":#", s);
							i++;
							continue;
						}
						case 'd':
						case 'D':
						{
							Style s = userTextPaneDocument.getStyle(":d");
							userTextPaneDocument.insertString(length+i, ":d", s);
							i++;
							continue;
						}
						case 'p':
						case 'P':
						{
							Style s = userTextPaneDocument.getStyle(":p");
							userTextPaneDocument.insertString(length+i, ":p", s);
							i++;
							continue;
						}
						case '(':
						{
							Style s = userTextPaneDocument.getStyle(":(");
							userTextPaneDocument.insertString(length+i, ":(", s);
							i++;
							continue;
						}
						case '$':
						{
							Style s = userTextPaneDocument.getStyle(":$");
							userTextPaneDocument.insertString(length+i, ":$", s);
							i++;
							continue;
						}
						case '@':
						{
							Style s = userTextPaneDocument.getStyle(":@");
							userTextPaneDocument.insertString(length+i, ":@", s);
							i++;
							continue;
						}
						case 'b':
						case 'B':
						{
							Style s = userTextPaneDocument.getStyle(":b");
							userTextPaneDocument.insertString(length+i, ":b", s);
							i++;
							continue;
						}
						case 'l':
						case 'L':
						{
							Style s = userTextPaneDocument.getStyle(":l");
							userTextPaneDocument.insertString(length+i, ":l", s);
							i++;
							continue;
						}
						case 'k':
						case 'K':
						{
							Style s = userTextPaneDocument.getStyle(":k");
							userTextPaneDocument.insertString(length+i, ":k", s);
							i++;
							continue;
						}
						case 'f':
						case 'F':
						{
							Style s = userTextPaneDocument.getStyle(":f");
							userTextPaneDocument.insertString(length+i, ":f", s);
							i++;
							continue;
						}
						case 'u':
						case 'U':
						{
							Style s = userTextPaneDocument.getStyle(":u");
							userTextPaneDocument.insertString(length+i, ":u", s);
							i++;
							continue;
						}
						case 'a':
						case 'A':
						{
							Style s = userTextPaneDocument.getStyle(":a");
							userTextPaneDocument.insertString(length+i, ":a", s);
							i++;
							continue;
						}
						case 'w':
						case 'W':
						{
							Style s = userTextPaneDocument.getStyle(":w");
							userTextPaneDocument.insertString(length+i, ":w", s);
							i++;
							continue;
						}
						case 'g':
						case 'G':
						{
							Style s = userTextPaneDocument.getStyle(":g");
							userTextPaneDocument.insertString(length+i, ":g", s);
							i++;
							continue;
						}
						case 'y':
						case 'Y':
						{
							Style s = userTextPaneDocument.getStyle(":y");
							userTextPaneDocument.insertString(length+i, ":y", s);
							i++;
							continue;
						}
						case 'n':
						case 'N':
						{
							Style s = userTextPaneDocument.getStyle(":n");
							userTextPaneDocument.insertString(length+i, ":n", s);
							i++;
							continue;
						}
						case 'c':
						case 'C':
						{
							Style s = userTextPaneDocument.getStyle(":c");
							userTextPaneDocument.insertString(length+i, ":c", s);
							i++;
							continue;
						}
						case 'r':
						case 'R':
						{
							Style s = userTextPaneDocument.getStyle(":r");
							userTextPaneDocument.insertString(length+i, ":r", s);
							i++;
							continue;
						}
						default:
							userTextPaneDocument.insertString(length+i, ":", null);
					}
				}
				else {
					userTextPaneDocument.insertString(length+i, Character.toString(chars[i]), null);
				}
			}
		}
		catch (BadLocationException e1) {
//			e1.printStackTrace();
		}
    }

    
}
